home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / redraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  18.7 KB  |  751 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: redraw.c 1.2 1994/09/09 12:31:30 digulla Exp digulla $
  5.  
  6.     DESCRIPTION
  7.     This contains all functionality that is needed to refresh
  8.     part of the display.
  9.  
  10.     $Log: redraw.c $
  11.  * Revision 1.2  1994/09/09  12:31:30  digulla
  12.  * made local functions static
  13.  * added new style Prototypes, DEFCMD and DEFHELP
  14.  *
  15.  * Revision 1.1  1994/08/19  14:03:12  digulla
  16.  * Initial revision
  17.  *
  18.  
  19. ******************************************************************************/
  20.  
  21. /**************************************
  22.         Includes
  23. **************************************/
  24. #include <defs.h>
  25. #define MYDEBUG     0
  26. #include "debug.h"
  27.  
  28.  
  29. /**************************************
  30.         Globale Variable
  31. **************************************/
  32.  
  33.  
  34. /**************************************
  35.       Interne Defines & Strukturen
  36. **************************************/
  37. #define SWAP(a,b)   (void)((a)^=(b),(b)^=(a),(a)^=(b))
  38. #define MIN(a,b)    ((a) <= (b) ? (a) : (b))
  39. #define MAX(a,b)    ((a) >= (b) ? (a) : (b))
  40. #define CLIP(l,m,h) (((m) < (l)) ? (l) : (((m) > (h)) ? (h) : (m)))
  41.  
  42. #define BF_LINESWAP        1L
  43. #define BF_COLUMNSWAP        2L
  44.  
  45. /* We note all areas that need to be drawn/erased in this structure.
  46.  
  47.     (startline<=endline && startcol<=endcol) == TRUE !
  48. */
  49.  
  50. #define NO_INTERSECT        0
  51. #define TOP_CLIP        0x0001
  52. #define BOTTOM_CLIP        0x0010
  53. #define LEFT_CLIP        0x0100
  54. #define RIGHT_CLIP        0x1000
  55. #define TOP_INTERSECT        0x0002
  56. #define BOTTOM_INTERSECT    0x0020
  57. #define LEFT_INTERSECT        0x0200
  58. #define RIGHT_INTERSECT     0x2000
  59.  
  60. #define IS_EMPTY        0
  61. #define NOT_EMPTY        1
  62. #define MEMORY_ERROR        2
  63.  
  64. struct RefreshRegion
  65. {
  66.     MLIST list;     /* linked list of regions */
  67. };
  68.  
  69. struct rect
  70. {
  71.     Line   sl;        /* line where the region starts in */
  72.     Column sc;        /* and the column */
  73.     Line   el;        /* same for end-pos */
  74.     Column ec;
  75. };
  76.  
  77.  
  78. struct MyRegion
  79. {
  80.     MNODE  node;    /* for linking into a list */
  81.     struct rect rect;
  82. };
  83.  
  84.  
  85. /**************************************
  86.         Interne Variable
  87. **************************************/
  88.  
  89.  
  90. /**************************************
  91.        Interne Prototypes
  92. **************************************/
  93. static struct RefreshRegion * new_region (void);
  94. static void dispose_region (struct RefreshRegion *);
  95. static UWORD do_clip (struct MyRegion *, struct rect *);
  96. static int and_rect_region (struct RefreshRegion *, struct rect *);
  97. static BOOL add_rect (struct RefreshRegion *, struct rect *);
  98. static int clear_rect_region (struct RefreshRegion *, struct rect *);
  99. static void refresh_region (RP *, struct RefreshRegion *, int);
  100. static void print_region (struct RefreshRegion *);
  101.  
  102.  
  103. /*****************************************************************************
  104.  
  105.     NAME
  106.     redraw_block
  107.  
  108.     PARAMETER
  109.     BOOL   force;        Shall I care for the difference between
  110.                 the fields in the ActualBlock or just
  111.                 redraw the block in the limits specified
  112.                 in the parameters ?
  113.     Line   start_line;
  114.     Column start_column;
  115.     Line   end_line;
  116.     Column end_column;
  117.  
  118.     RETURN
  119.     void
  120.  
  121.     DESCRIPTION
  122.     This function draws a block according to the type. The parameter
  123.     force has a special meaning. If it is TRUE, you force a redraw.
  124.     The block is newly drawn. In this case, the lines specify the
  125.     clip-rect of text that is to be redrawn.
  126.         If it is FALSE, the positions specify the new start- and
  127.     end-positions for the block. The routine gurantees that the
  128.     start-position of the block is before the end-position after the
  129.     call. It is valid to call the routine with -1/-1 for one position.
  130.     In this case, you just want to move one position without touching
  131.     the other. The routine also takes care for flipping the block.
  132.  
  133.     NOTES
  134.     - If force is FALSE, you MUST NOT change more than one position at
  135.       a time. You can exchange both and change one, though.
  136.     - The block is only redrawn, if the actual editor is the editor
  137.       with the block and drawing in that editor is ok !
  138.     - After the call, the new positions are written into the ActualBlock-
  139.       struct if force is FALSE. It is guranteed, that the start-position
  140.       is before the end-position, no matter how they were when the routine
  141.       was called.
  142.  
  143. ******************************************************************************/
  144.  
  145. static void print_region (struct RefreshRegion * region)
  146. {
  147.     struct MyRegion * ptr;
  148.     int t;
  149.  
  150.     for (t=0,ptr=GetHead(®ion->list); ptr; ptr=GetSucc(&ptr->node),t++)
  151.     {
  152.     D(bug("Node %ld: (%ld/%ld) - (%ld/%ld)\n",
  153.         t, ptr->rect.sl, ptr->rect.sc, ptr->rect.el, ptr->rect.ec));
  154.     }
  155. } /* print_region */
  156.  
  157.  
  158. static struct RefreshRegion * new_region (void)
  159. {
  160.     struct RefreshRegion * new;
  161.  
  162.     if (new = AllocMem (sizeof(struct RefreshRegion), 0))
  163.     {
  164.     NewList ((struct List *)&new->list);
  165.     }
  166.  
  167.     return (new);
  168. } /* new_region */
  169.  
  170.  
  171. static void dispose_region (struct RefreshRegion * region)
  172. {
  173.     struct MyRegion * ptr, * next;
  174.  
  175.     for (ptr=GetHead(®ion->list); ptr; ptr=next)
  176.     {
  177.     next = GetSucc (&ptr->node);
  178.  
  179.     FreeMem (ptr, sizeof(struct MyRegion));
  180.     }
  181.  
  182.     FreeMem (region, sizeof(struct RefreshRegion));
  183. } /* dispose_region */
  184.  
  185.  
  186. static UWORD do_clip (struct MyRegion * region, struct rect * rect)
  187. {
  188.     UWORD test = NO_INTERSECT;
  189.  
  190.     if (!(  (region->rect.sl > rect->el) || (region->rect.el < rect->sl) ||
  191.         (region->rect.sc > rect->ec) || (region->rect.ec < rect->sc) ) )
  192.     {
  193.     if (region->rect.sl < rect->sl)
  194.         test |= TOP_CLIP;
  195.  
  196.     if (region->rect.el > rect->el)
  197.         test |= BOTTOM_CLIP;
  198.  
  199.     if (region->rect.sc < rect->sc)
  200.         test |= LEFT_CLIP;
  201.  
  202.     if (region->rect.ec > rect->ec)
  203.         test |= RIGHT_CLIP;
  204.  
  205.     if (region->rect.sl <= rect->el)
  206.         test |= TOP_INTERSECT;
  207.  
  208.     if (region->rect.el >= rect->sl)
  209.         test |= BOTTOM_INTERSECT;
  210.  
  211.     if (region->rect.sc <= rect->ec)
  212.         test |= LEFT_INTERSECT;
  213.  
  214.     if (region->rect.ec >= rect->sc)
  215.         test |= RIGHT_INTERSECT;
  216.     }
  217.  
  218.     /* D(bug("clip %04lx\n", test)); */
  219.  
  220.     return (test);
  221. } /* do_clip */
  222.  
  223.  
  224. /* clip regions */
  225.  
  226. static int and_rect_region (struct RefreshRegion * region, struct rect * rect)
  227. {
  228.     struct MyRegion * ptr, * next;
  229.     UWORD status;
  230.  
  231.     for (ptr=GetHead(®ion->list); ptr; ptr=next)
  232.     {
  233.     UWORD common;
  234.  
  235.     next = GetSucc (&ptr->node);
  236.  
  237.     if ((common = do_clip (ptr, rect)) != NO_INTERSECT)
  238.     {
  239.         if (common & TOP_CLIP)
  240.         ptr->rect.sl = rect->sl;
  241.  
  242.         if (common & BOTTOM_CLIP)
  243.         ptr->rect.el = rect->el;
  244.  
  245.         if (common & LEFT_CLIP)
  246.         ptr->rect.sc = rect->sc;
  247.  
  248.         if (common & RIGHT_CLIP)
  249.         ptr->rect.ec = rect->ec;
  250.     }
  251.     else
  252.     {
  253.         /* if they do not intersect, remove the Region */
  254.  
  255.         Remove ((struct Node *)&ptr->node);
  256.  
  257.         FreeMem (ptr, sizeof(struct MyRegion));
  258.     }
  259.     }
  260.  
  261.     if (!GetHead(region))
  262.     status = IS_EMPTY;
  263.     else
  264.     status = NOT_EMPTY;
  265.  
  266.     return (status);
  267. } /* and_rect_region */
  268.  
  269.  
  270. /* make a copy of a region */
  271.  
  272. static struct RefreshRegion * copy_region (struct RefreshRegion * region)
  273. {
  274.     struct MyRegion * ptr;
  275.     struct RefreshRegion * copy;
  276.  
  277.     if (copy = new_region ())
  278.     {
  279.     for (ptr=GetHead(®ion->list); ptr; ptr=GetSucc(&ptr->node))
  280.     {
  281.         if (!(add_rect (copy, &ptr->rect)) )
  282.         {
  283.         dispose_region (copy);
  284.  
  285.         return (NULL);
  286.         }
  287.     }
  288.     }
  289.  
  290.     return (copy);
  291. } /* copy_region */
  292.  
  293.  
  294. /* make erase all common areas between two regions */
  295.  
  296. static void clip_region (struct RefreshRegion * region, struct RefreshRegion * clip)
  297. {
  298.     struct MyRegion * ptr;
  299.  
  300.     for (ptr=GetHead(&clip->list); ptr; ptr=GetSucc(&ptr->node))
  301.     {
  302.     clear_rect_region (region, &ptr->rect);
  303.     }
  304. } /* clip_region */
  305.  
  306.  
  307. /* create a new Region and add it to the RefreshRegion. This routine
  308.    must not be called with a rect that intersects with any of the
  309.    Regions that are already in the RefreshRegion ! */
  310.  
  311. static BOOL add_rect (struct RefreshRegion * region, struct rect * rect)
  312. {
  313.     struct MyRegion * new;
  314.  
  315.     if (new = AllocMem (sizeof(struct MyRegion), 0))
  316.     {
  317.     movmem (rect, &new->rect, sizeof (struct rect));
  318.  
  319.     /* AddHead because we might be editing the list right now :-) */
  320.     AddHead ((struct List *)®ion->list, (struct Node *)&new->node);
  321.     }
  322.  
  323.     return ((BOOL)(new != NULL));
  324. } /* add_rect */
  325.  
  326.  
  327. /* adjust regions that none intersects with the rect anymore */
  328.  
  329. static int clear_rect_region (struct RefreshRegion * region, struct rect * rect)
  330. {
  331.     struct MyRegion * ptr, * next;
  332.     UWORD status;
  333.  
  334.     for (ptr=GetHead(®ion->list); ptr; ptr=next)
  335.     {
  336.     UWORD common;
  337.     struct rect new_rect;
  338.  
  339.     next = GetSucc (&ptr->node);
  340.  
  341.     /* do something only if we have an intersection */
  342.  
  343.     if ((common = do_clip (ptr, rect)) != NO_INTERSECT)
  344.     {
  345.         /* if both intersect, we make sure we don't have any areas left
  346.            that are in two Regions */
  347.  
  348.         if (common & TOP_CLIP)
  349.         {
  350.         /* if we have a TOP_CLIP, there must be some new Region
  351.            above. */
  352.  
  353.         new_rect.sl = ptr->rect.sl;
  354.         new_rect.el = rect->sl - 1;    /* this is the intersection */
  355.         new_rect.sc = ptr->rect.sc;
  356.         new_rect.ec = ptr->rect.ec;
  357.  
  358.         /* is this a valid rect anyway ?? */
  359.         if (new_rect.sl <= new_rect.el)
  360.         {
  361.             if (!add_rect (region, &new_rect))
  362.             return (MEMORY_ERROR);
  363.             else
  364.             ptr->rect.sl = rect->sl;   /* new topline */
  365.         } /* valid rect ? */
  366.         } /* type of intersect */
  367.  
  368.         if (common & BOTTOM_CLIP)
  369.         {
  370.         /* if we have a BOTTOM_CLIP, there must be some new Region
  371.            below. */
  372.  
  373.         new_rect.sl = rect->el + 1;    /* clipping */
  374.         new_rect.el = ptr->rect.el;
  375.         new_rect.sc = ptr->rect.sc;
  376.         new_rect.ec = ptr->rect.ec;
  377.  
  378.         /* is this a valid rect anyway ?? */
  379.         if (new_rect.sl <= new_rect.el)
  380.         {
  381.             if (!add_rect (region, &new_rect))
  382.             return (MEMORY_ERROR);
  383.             else
  384.             ptr->rect.el = rect->el;
  385.         } /* valid rect ? */
  386.         } /* type of intersect */
  387.  
  388.         if (common & LEFT_CLIP)
  389.         {
  390.         /* if we have a LEFT_CLIP, there must be some new Region
  391.            below. */
  392.  
  393.         new_rect.sl = ptr->rect.sl;
  394.         new_rect.el = ptr->rect.el;
  395.         new_rect.sc = ptr->rect.sc;
  396.         new_rect.ec = rect->sc - 1;    /* clipping */
  397.  
  398.         /* is this a valid rect anyway ?? */
  399.         if (new_rect.sc <= new_rect.ec)
  400.         {
  401.             if (!add_rect (region, &new_rect))
  402.             return (MEMORY_ERROR);
  403.  
  404.             /* we do not need any ELSE here since RIGHT_CLIP
  405.                doesn't care about the left border. */
  406.  
  407.         } /* valid rect ? */
  408.         } /* type of intersect */
  409.  
  410.         if (common & RIGHT_CLIP)
  411.         {
  412.         /* if we have a RIGHT_CLIP, there must be some new Region
  413.            below. */
  414.  
  415.         new_rect.sl = ptr->rect.sl;
  416.         new_rect.el = ptr->rect.el;
  417.         new_rect.sc = rect->ec + 1;    /* clipping */
  418.         new_rect.ec = ptr->rect.ec;
  419.  
  420.         /* is this a valid rect anyway ?? */
  421.         if (new_rect.sc <= new_rect.ec)
  422.         {
  423.             if (!add_rect (region, &new_rect))
  424.             return (MEMORY_ERROR);
  425.         } /* valid rect ? */
  426.         } /* type of intersect */
  427.  
  428.         /* remove old area */
  429.         Remove ((struct Node *)&ptr->node);
  430.  
  431.         FreeMem (ptr, sizeof (struct MyRegion));
  432.     } /* intersection */
  433.     }
  434.  
  435.     if (!GetHead(region))
  436.     status = IS_EMPTY;
  437.     else
  438.     status = NOT_EMPTY;
  439.  
  440.     return (status);
  441. } /* clear_rect_region */
  442.  
  443.  
  444. static int AddDrawEvent (struct RefreshRegion * region, Line sl, Column sc,
  445.         Line el, Column ec)
  446. {
  447.     struct rect new_rect;
  448.  
  449.     if (el < sl || ec < sc) /* don't add invalid blocks */
  450.     return (TRUE);
  451.  
  452.     new_rect.sl = sl;
  453.     new_rect.el = el;
  454.     new_rect.sc = sc;
  455.     new_rect.ec = ec;
  456.  
  457.     return (add_rect (region, &new_rect));
  458. } /* AddDrawEvent */
  459.  
  460. static int add_block_draw_events( struct RefreshRegion *region )
  461.   {
  462.     Line sl, el;
  463.  
  464.     sl = el = ActualBlock.start_line;
  465.     AddDrawEvent (region, sl, block_leftcolumn ( sl ), el, block_rightcolumn( el ) );
  466.  
  467.     sl = ActualBlock.start_line + 1;
  468.     el = ActualBlock.end_line    - 1;
  469.     AddDrawEvent (region, sl, block_leftcolumn ( sl ), el, block_rightcolumn( el ) );
  470.  
  471.     sl = el = ActualBlock.end_line;
  472.     AddDrawEvent (region, sl, block_leftcolumn ( sl ), el, block_rightcolumn( el ) );
  473.  
  474.     return TRUE;  /* Really should check these values some day... */
  475.   }
  476.  
  477. /*****************************************************************************
  478.  
  479.     NAME
  480.     redraw_block
  481.  
  482.     PARAMETER
  483.     BOOL   force;
  484.     Line   start_line;
  485.     Column start_column;
  486.     Line   end_line;
  487.     Column end_column;
  488.  
  489.     RESULT
  490.  
  491.     RETURN
  492.     void
  493.  
  494.     DESCRIPTION
  495.     Draws part of the text (force = TRUE) or adjust the block
  496.     according to the new coordinates (force = FALSE).
  497.  
  498.     NOTES
  499.  
  500.     BUGS
  501.  
  502.     EXAMPLES
  503.  
  504.     SEE ALSO
  505.  
  506.     INTERNALS
  507.  
  508.     HISTORY
  509.     03. Jan 1978    ada created
  510.  
  511. ******************************************************************************/
  512.  
  513. Prototype void redraw_block (BOOL force, Line start_line, Column start_column, Line end_line, Column end_column);
  514.  
  515. void redraw_block (BOOL force, Line start_line, Column start_column, Line end_line, Column end_column)
  516. {
  517.     RP * rp;
  518.     struct RefreshRegion * old,     /* the old block that has to be erased */
  519.              * new,     /* the new block that has to be drawn */
  520.              * update,  /* region where we have to redraw the
  521.                        text */
  522.              * copy;    /* and a copy of old for removing common
  523.                        areas. */
  524.     struct rect new_rect;
  525.  
  526.     // ActualBlock.flags = 0; /* Should fail; ActualBlock should be const */
  527.  
  528.     D(bug("----> redraw_block\nforce:%ld    start:%3ld/%3ld  end:%3ld/%3ld\n",
  529.         force,
  530.         start_line+1, start_column+1,
  531.         end_line+1, end_column+1 ));
  532.  
  533.     if (GETF_COMLINEMODE(Ep))
  534.     {
  535.     text_redraw_cmdline ();
  536.     return;
  537.     }
  538.  
  539.     old    = new_region ();
  540.     new    = new_region ();
  541.     update = new_region ();
  542.  
  543.     if (!old || !new || !update)    /* out of memory */
  544.     return;
  545.  
  546.     if ( !block_ok () || ActualBlock.ep != Ep) /* no block to worry about */
  547.     {
  548. update_only:         /* jump here if we are sure there is no block to draw */
  549.  
  550.     D(bug("Update only\n"));
  551.  
  552.     if (end_line < start_line)
  553.         SWAP(start_line,end_line);
  554.  
  555.     if (end_column < start_column)
  556.         SWAP(start_column,end_column);
  557.  
  558.     AddDrawEvent (update, start_line, start_column,
  559.         end_line, end_column);
  560.  
  561.     goto draw;    /* I really don't like goto but I also don't
  562.                want to indent all those mush below :-) */
  563.     }
  564.  
  565.     else /* deal with the block stuff */
  566.     /* find drawing positions. After this if, the redraw-struct is filled with
  567.        all information to draw the new situation */
  568.     if (force)
  569.     {
  570.     short part;
  571.     Line sl, el;
  572.     /* here, we must make sure, that start <= end ! */
  573.     if (start_line > end_line)
  574.     {
  575.         SWAP (start_line,   end_line   );
  576.         SWAP (start_column, end_column );
  577.     } else if (start_line  == end_line &&
  578.            start_column > end_column )
  579.         SWAP (start_column, end_column);
  580.  
  581.     /* clip end-line */
  582.     if (end_line >= Ep->lines)
  583.         end_line = Ep->lines-1;
  584.  
  585.     /* clip all areas against the draw-area */
  586.     new_rect.sl = start_line;
  587.     new_rect.el = end_line;
  588.     new_rect.sc = start_column;
  589.     new_rect.ec = end_column;
  590.  
  591.         /* The situation is like this :
  592.  
  593.           +-----------------------+
  594.           |         (A)          |   (A)  The area above the block
  595.           |         +---------+  +   (B)  The area in the line where
  596.           |  (B)     |     (C) |  |        the block starts BEFORE the
  597.           +  +-------+ - - - - +  +       block
  598.           |  |        (D)        |  |   (C)  The area inside the block in
  599.           +  + - - - - -+------+  +       the line where the block
  600.           |  | (E)      |   (F)   |        begins
  601.           +  +----------+      |   (D)  the main body
  602.           |         (G)          |   (E)  the rest of the block in the
  603.           +-----------------------+       last line
  604.                           (F)  the rest of this line
  605.                           (G)  anything below the block
  606.  
  607.         */
  608.     /* region (A) above the block */
  609.     AddDrawEvent (update, start_line, start_column,
  610.             ActualBlock.start_line - 1, end_column);
  611.  
  612.     for ( part=0; part<3; part++ )
  613.       {
  614.         switch (part )
  615.           {
  616.         case 0: sl =
  617.             el = ActualBlock.start_line;       break;
  618.         case 1: sl = ActualBlock.start_line + 1;
  619.             el = ActualBlock.end_line   - 1;   break;
  620.         case 2: sl =
  621.             el = ActualBlock.end_line;       break;
  622.           } /* switch(part)
  623.  
  624.         /* left of block */
  625.         AddDrawEvent (update, sl, start_column, el, block_leftcolumn(el)-1 );
  626.  
  627.         /* right of block */
  628.         AddDrawEvent (update, sl, block_rightcolumn(sl) + 1, el, end_column );
  629.       }
  630.     /* region (G) below the block */
  631.     AddDrawEvent (update, ActualBlock.end_line + 1, start_column,
  632.             end_line, end_column);
  633.  
  634.     /* The block itself (C,D,E) */
  635.     add_block_draw_events( new );
  636.  
  637.     and_rect_region (update, &new_rect);
  638.     and_rect_region (new, &new_rect);
  639.  
  640.     /* D(bug("Update :\n")); print_region (update);
  641.        D(bug("new :\n")); print_region (new); */
  642.     } else /* force == FALSE */
  643.     {
  644.     /* unhighlight the old block */
  645.     add_block_draw_events( old );
  646.  
  647.     /* update the block coordinates */
  648.     if ( start_line != -1 )
  649.         set_block_start( start_line, start_column );
  650.  
  651.     if ( end_line != -1 )
  652.         set_block_end( end_line, end_column );
  653.  
  654.     /* highlight the new block */
  655.     add_block_draw_events( new );
  656.  
  657.     copy = copy_region (old);       /* make a copy of the old block */
  658.  
  659.     clip_region (old, new);         /* clear all common areas in old */
  660.     clip_region (new, copy);        /* clear all common areas in new */
  661.  
  662.     dispose_region (copy);          /* free copy */
  663.  
  664.     } /* if (force) */
  665.  
  666. draw:        /* jump here is all DrawEvents are correctly initialized */
  667.  
  668.     /* Are we allowed to draw ? */
  669.     if (!Nsu && !GETF_ICONMODE(Ep))
  670.     {
  671.     /* init rastport */
  672.     rp = Ep->win->RPort;
  673.  
  674.     /* clip the update-region */
  675.     new_rect.sl = Ep->topline;
  676.     new_rect.el = new_rect.sl + Lines - 1;
  677.     new_rect.sc = Ep->topcolumn;
  678.     new_rect.ec = new_rect.sc + Columns - 1;
  679.  
  680.     /* make sure we don't get below the last line */
  681.     if (new_rect.el >= Ep->lines)
  682.         new_rect.el = Ep->lines - 1;
  683.  
  684.     /* clip away everything that exceeds the displayable area */
  685.     and_rect_region (update, &new_rect);
  686.     and_rect_region (old, &new_rect);
  687.     and_rect_region (new, &new_rect);
  688.  
  689.     refresh_region (rp, update, 2);
  690.     refresh_region (rp, old, 0);
  691.     refresh_region (rp, new, 1);
  692.  
  693.     dispose_region (update);
  694.     dispose_region (old);
  695.     dispose_region (new);
  696.     }
  697. } /* redraw_block */
  698.  
  699.  
  700. static void refresh_region (RP * rp, struct RefreshRegion * region, int mode)
  701. {
  702.     struct MyRegion * ptr;
  703.     Line start_line, end_line;
  704.     Column start_column, end_column;
  705.     D(int t=0);
  706.  
  707.     for (ptr=GetHead(®ion->list); ptr; ptr=GetSucc(&ptr->node))
  708.     {
  709.     start_line   = ptr->rect.sl;
  710.     end_line     = ptr->rect.el;
  711.     start_column = ptr->rect.sc;
  712.     end_column   = ptr->rect.ec + 1;
  713.  
  714.     D(bug("Draw %ld: %ld (%2ld,%2ld) - (%2ld/%2ld)\n", t ++,
  715.         mode, start_line+1, start_column+1, end_line+1, end_column+1));
  716.  
  717.     if (start_line > end_line ||
  718.         start_column >= end_column)
  719.     {
  720.         D(bug("ERROR !!!!\n"));
  721.         continue;
  722.     }
  723.  
  724.     if (mode != 2)
  725.     {
  726.         if (mode == 1)
  727.         SetAPen (rp, BLOCK_BPEN(Ep));
  728.         else
  729.         SetAPen (rp, TEXT_BPEN(Ep));
  730.  
  731.         SetWrMsk (rp, BLOCK_MASK(Ep));
  732.         SetDrMd (rp, JAM2);
  733.  
  734.         RectFill (rp, COL(start_column - Ep->topcolumn),
  735.             ROW(start_line - Ep->topline),
  736.             COL(end_column - Ep->topcolumn)-1,
  737.             ROW(end_line + 1 - Ep->topline)-1 );
  738.  
  739.         SetWrMsk (rp, ALL_MASK);
  740.     }
  741.  
  742.     for ( ; start_line <= end_line; start_line ++)
  743.         redraw_textlineseg (start_line, start_column, end_column);
  744.     }
  745. } /* refresh_region */
  746.  
  747.  
  748. /******************************************************************************
  749. *****  ENDE redraw.c
  750. ******************************************************************************/
  751.